package com.yl.demo.web;

import com.yl.demo.utils.BaseUtil;
import com.yl.demo.utils.redis.RedisUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/")
public class HelloController {

    private final static Logger logger = LoggerFactory.getLogger(HelloController.class);

    private final String X_AUTH_TOKEN = "AuthorizationToken";

    @Resource
    private RedisUtils redisUtils;
    /**
     * Spring Boot中使用模板引擎freemarker
     *
     * @param map
     * @return
     */
    @RequestMapping("/fremark")
    public String fremark(Map<String, Object> map) {
        map.put("name", "YL---注孤生");
        map.put("gender", 1);//gender:性别，1：男；0：女；

        List<Map<String, Object>> friends = new ArrayList<Map<String, Object>>();
        Map<String, Object> friend = new HashMap<String, Object>();
        friend.put("name", "张三");
        friend.put("age", 20);
        friends.add(friend);
        friend = new HashMap<String, Object>();
        friend.put("name", "李四");
        friend.put("age", 22);
        friends.add(friend);
        map.put("friends", friends);
        logger.info("Index 注入模板引擎数据，{}", map.toString());
        return "fremark";
    }


    /**
     * @return
     * @Description: login
     * @author YL
     * @date 2018/10/24 12:26
     */
    @RequestMapping(value = "/loginback", method = RequestMethod.POST)
    public String doLogin(HttpServletRequest request, @RequestParam String username, @RequestParam String password) {
        logger.info("调用Login方法，{}");
        logger.info("userName==="+username+"    password=="+password);
        // 登录失败从request中获取shiro处理的异常信息。
        //添加用户认证信息
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
               username,
                password);
        //进行验证，这里可以捕获异常，然后返回对应信息
        subject.login(usernamePasswordToken);
        // shiroLoginFailure:就是shiro异常类的全类名.
        String exception = (String) request.getAttribute("shiroLoginFailure");

        logger.info("exception=" + exception + "    " + request.getParameter("username"));
        String msg = "";
        if (exception != null) {
            if (UnknownAccountException.class.getName().equals(exception)) {
                logger.info("UnknownAccountException -- > 账号不存在：");
                msg = "UnknownAccountException -- > 账号不存在：";
            } else if (IncorrectCredentialsException.class.getName().equals(exception)) {
                logger.info("IncorrectCredentialsException -- > 密码不正确：");
                msg = "IncorrectCredentialsException -- > 密码不正确：";
            } else if ("kaptchaValidateFailed".equals(exception)) {
                logger.info("kaptchaValidateFailed -- > 验证码错误");
                msg = "kaptchaValidateFailed -- > 验证码错误";
            } else {
                msg = "else >> " + exception;
                logger.info("else -- >" + exception);
            }
        }
        // 此方法不处理登录成功,由shiro进行处理.
        logger.info("调用Login方法，{}", "登录完成");
        return "success";
    }

    @RequestMapping("/login")
    @ResponseBody
    public Map<String, Object> login(@RequestParam String username, @RequestParam String password, HttpServletRequest request, HttpSession session) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);
        map.put("message", "登陆成功");
        logger.info("login--username=["+username+"], password=["+password+"]" );
        // 获得当前Subject
        Subject currentUser = SecurityUtils.getSubject();
        // 验证用户是否验证，即是否登录
        if (!currentUser.isAuthenticated()) {
            String msg = "";
            // 把用户名和密码封装为 UsernamePasswordToken 对象
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);

            // remembermMe记住密码
            token.setRememberMe(true);
            try {
                // 执行登录.
                currentUser.login(token);

            } catch (IncorrectCredentialsException e) {
                msg = "登录密码错误";
                logger.info("登录密码错误!!!" + e);
            } catch (ExcessiveAttemptsException e) {
                msg = "登录失败次数过多";
                logger.info("登录失败次数过多!!!" + e);
            } catch (LockedAccountException e) {
                msg = "帐号已被锁定";
                logger.info("帐号已被锁定!!!" + e);
            } catch (DisabledAccountException e) {
                msg = "帐号已被禁用";
                logger.info("帐号已被禁用!!!" + e);
            } catch (ExpiredCredentialsException e) {
                msg = "帐号已过期";
                logger.info("帐号已过期!!!" + e);
            } catch (UnknownAccountException e) {
                msg = "帐号不存在";
                logger.info("帐号不存在!!!" + e);
            } catch (UnauthorizedException e) {
                msg = "您没有得到相应的授权！";
                logger.info("您没有得到相应的授权！" + e);
            } catch (Exception e) {
                e.printStackTrace();
                logger.info("出错！！！" + e);
            }
            if (StringUtils.isNotBlank(msg)){
                map.put("code", 205);
                map.put("message", msg);
                logger.info("调用Login方法，{}", "登录error");
            }else{
                map.put("data", redisUtils.get(this.X_AUTH_TOKEN));
            }
        }
        // 登录成功，重定向到LoginSuccess.action
        logger.info("调用Login方法，{}", "登录完成["+ BaseUtil.toJSON(map)+"]");
        return map;
    }


    /**
     * 未登录，shiro应重定向到登录界面，此处返回未登录状态信息由前端控制跳转页面
     * @return
     */
    @RequestMapping(value = "/unauth")
    @ResponseBody
    public Object unauth() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", "1000000");
        map.put("msg", "未登录");
        return map;
    }

    @RequestMapping(value = "/successbak")
    public String success() {
        logger.info("调用success方法，{}");
        return "success";
    }

    @RequestMapping(value = "/loginbak")
    public String login() {
        logger.info("调用login.HTML方法，{}");
        return "login";
    }


}
